/**
 * @file   MethodInfo.cpp
 * @author Djuro Drljaca (djurodrljaca@gmail.com)
 * @date   2013-05-19
 * @brief  DataBus Value Info.
 *
 * Copyright (C) 2013 Djuro Drljaca <djurodrljaca@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <DataBus/Common/MethodInfo.h>

DataBus::MethodInfo::MethodInfo()
    : m_id(0),
      m_name(),
      m_parameterInfoList(),
      m_returnValueInfoList(),
      m_valid(true)
{
}

DataBus::MethodInfo::MethodInfo(const quint8 id,
                                const QString &name,
                                const QList<ValueInfo> &parameterInfoList,
                                const QList<ValueInfo> &returnValueInfoList)
    : m_id(id),
      m_name(),
      m_parameterInfoList(),
      m_returnValueInfoList(),
      m_valid(false)
{
    // Check name
    if (name.toUtf8().size() > STRING_MAX_LENGTH)
    {
        return;
    }

    // Check parameter info list
    if (parameterInfoList.size() > 255)
    {
        return;
    }

    for (int i = 0; i < parameterInfoList.size(); i++)
    {
        if (parameterInfoList.at(i).isValid() == false)
        {
            return;
        }
    }

    // Check return value info list
    if (returnValueInfoList.size() > 255)
    {
        return;
    }

    for (int i = 0; i < returnValueInfoList.size(); i++)
    {
        if (returnValueInfoList.at(i).isValid() == false)
        {
            return;
        }
    }

    // Save name, parameter and return value info lists
    m_name = name;
    m_parameterInfoList = parameterInfoList;
    m_returnValueInfoList = returnValueInfoList;

    m_valid = true;
}

DataBus::MethodInfo::MethodInfo(const MethodInfo &copyin)
    : m_id(copyin.m_id),
      m_name(copyin.m_name),
      m_parameterInfoList(copyin.m_parameterInfoList),
      m_returnValueInfoList(copyin.m_returnValueInfoList)
{
}

DataBus::MethodInfo & DataBus::MethodInfo::operator=(const MethodInfo &rhs)
{
    m_id = rhs.m_id;
    m_name = rhs.m_name;
    m_parameterInfoList = rhs.m_parameterInfoList;
    m_returnValueInfoList = rhs.m_returnValueInfoList;
    m_valid = rhs.m_valid;

    return *this;
}

bool DataBus::MethodInfo::isValid() const
{
    return m_valid;
}

quint8 DataBus::MethodInfo::getId() const
{
    return m_id;
}

void DataBus::MethodInfo::setId(const quint8 id)
{
    m_id = id;
}

QString DataBus::MethodInfo::getName() const
{
    return m_name;
}

bool DataBus::MethodInfo::setName(const QString &name)
{
    // Check name
    if (name.toUtf8().size() > STRING_MAX_LENGTH)
    {
        // Error, name is too long
        return false;
    }

    // Save name
    m_name = name;

    // Success
    return true;
}

QList<DataBus::ValueInfo> DataBus::MethodInfo::getParameterInfoList() const
{
    return m_parameterInfoList;
}

bool DataBus::MethodInfo::setParameterInfoList(const QList<ValueInfo> &parameterInfoList)
{
    // Check parameter info list
    if (parameterInfoList.size() > 255)
    {
        // Error, too many parameters
        return false;
    }

    for (int i = 0; i < parameterInfoList.size(); i++)
    {
        if (parameterInfoList.at(i).isValid() == false)
        {
            // Error, invalid parameter info
            return false;
        }
    }

    // Save parameter info list
    m_parameterInfoList = parameterInfoList;

    // Success
    return true;
}

quint8 DataBus::MethodInfo::getNoOfParameters() const
{
    return static_cast<quint8>(m_parameterInfoList.size());
}

bool DataBus::MethodInfo::getParameterInfo(const quint8 index, ValueInfo *parameterInfo) const
{
    // Check parameters
    if ((index >= m_parameterInfoList.size()) ||
        (parameterInfo == 0))
    {
        // Error, invalid parameters
        return false;
    }

    // Return parameter info
    *parameterInfo = m_parameterInfoList.at(index);

    // Success
    return true;
}

bool DataBus::MethodInfo::getParameterInfo(const QString &name, ValueInfo *parameterInfo) const
{
    // Check parameters
    if (parameterInfo == 0)
    {
        // Error, invalid parameters
        return false;
    }

    // Find parameter info
    for (int i = 0; i < m_parameterInfoList.size(); i++)
    {
        if (m_parameterInfoList.at(i).getName() == name)
        {
            // Return parameter info
            *parameterInfo = m_parameterInfoList.at(i);

            // Success
            return true;
        }
    }

    // Error, failed to find the requested parameter info
    return false;
}

bool DataBus::MethodInfo::addParameterInfo(const ValueInfo &parameterInfo)
{
    // Check parameters
    if (parameterInfo.isValid() == false)
    {
        // Error, invalid parameters
        return false;
    }

    // Add parameter info to list
    m_parameterInfoList.append(parameterInfo);

    // Success
    return true;
}

QList<DataBus::ValueInfo> DataBus::MethodInfo::getReturnValueInfoList() const
{
    return m_returnValueInfoList;
}

bool DataBus::MethodInfo::setReturnValueInfoList(const QList<ValueInfo> &returnValueInfoList)
{
    // Check return value info list
    if (returnValueInfoList.size() > 255)
    {
        // Error, too many return values
        return false;
    }

    for (int i = 0; i < returnValueInfoList.size(); i++)
    {
        if (returnValueInfoList.at(i).isValid() == false)
        {
            // Error, invalid return value info
            return false;
        }
    }

    // Save return value info list
    m_returnValueInfoList = returnValueInfoList;

    // Success
    return true;
}

quint8 DataBus::MethodInfo::getNoOfReturnValues() const
{
    return static_cast<quint8>(m_returnValueInfoList.size());
}

bool DataBus::MethodInfo::getReturnValueInfo(const quint8 index, ValueInfo *returnValueInfo) const
{
    // Check parameters
    if ((index >= m_returnValueInfoList.size()) ||
        (returnValueInfo == 0))
    {
        // Error, invalid parameters
        return false;
    }

    // Return return value info
    *returnValueInfo = m_returnValueInfoList.at(index);

    // Success
    return true;
}

bool DataBus::MethodInfo::getReturnValueInfo(const QString &name, ValueInfo *returnValueInfo) const
{
    // Check parameters
    if (returnValueInfo == 0)
    {
        // Error, invalid parameters
        return false;
    }

    // Find return value info
    for (int i = 0; i < m_returnValueInfoList.size(); i++)
    {
        if (m_returnValueInfoList.at(i).getName() == name)
        {
            // Return return value info
            *returnValueInfo = m_returnValueInfoList.at(i);

            // Success
            return true;
        }
    }

    // Error, failed to find the requested return value info
    return false;
}

bool DataBus::MethodInfo::addReturnValueInfo(const ValueInfo &returnValueInfo)
{
    // Check parameters
    if (returnValueInfo.isValid() == false)
    {
        // Error, invalid parameters
        return false;
    }

    // Add return value info to list
    m_parameterInfoList.append(returnValueInfo);

    // Success
    return true;
}
